package main

import (
	"fmt"
	"strings"
	"time"
)

type Task struct {
	Name        string
	Description string
	Status      string
}

type TaskBot struct {
	Tasks      []Task
	AddTask    chan Task
	Quit       chan bool
	RemoveTask chan Task
}

func NewTaskBot() *TaskBot {
	tb := &TaskBot{
		Tasks:      make([]Task, 0),
		AddTask:    make(chan Task),
		Quit:       make(chan bool),
		RemoveTask: make(chan Task),
	}

	go func() {
		for {
			select {
			case task := <-tb.AddTask:
				tb.Tasks = append(tb.Tasks, task)
			case task := <-tb.RemoveTask:
				tb.removeTask(task)
			case <-tb.Quit:
				return
			default:
				if len(tb.Tasks) == 0 {
					// No tasks, keep listening
					time.Sleep(1 * time.Second)
					continue
				}
				task := tb.Tasks[0]
				go tb.executeTask(task)
				tb.removeTask(task)
			}
		}
	}()

	return tb
}

func (tb *TaskBot) removeTask(task Task) {
	for i, t := range tb.Tasks {
		if t.Name == task.Name {
			tb.Tasks = append(tb.Tasks[:i], tb.Tasks[i+1:]...)
			break
		}
	}
}

func (tb *TaskBot) AddNewTask(name, description string) {
	task := Task{
		Name:        name,
		Description: description,
		Status:      "Pending",
	}
	tb.AddTask <- task
}

func (tb *TaskBot) ListTasks() {
	for _, task := range tb.Tasks {
		fmt.Printf("Task: %s\nDescription: %s\nStatus: %s\n\n", task.Name, task.Description, task.Status)
	}
}

func (tb *TaskBot) executeTask(task Task) {
	fmt.Printf("Executing task: %s\n", task.Name)
	time.Sleep(3 * time.Second) // Simulating task execution time
	tb.UpdateTaskStatus(task.Name, "Completed")
}

func (tb *TaskBot) UpdateTaskStatus(name, status string) {
	for i, task := range tb.Tasks {
		if strings.EqualFold(task.Name, name) {
			tb.Tasks[i].Status = status
			break
		}
	}
}

func main() {
	bot := NewTaskBot()

	bot.AddNewTask("Complete homework", "Finish math assignment by tomorrow")
	bot.AddNewTask("Go to the gym", "Workout for at least an hour")
	bot.AddNewTask("Buy groceries", "Get milk, eggs, and bread")

	bot.ListTasks()

	fmt.Println("\nExecuting tasks...")
	bot.Quit <- true
}
